﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Security.Cryptography;
using System.Threading.Tasks;

namespace ConsoleApplication1
{
    public class DirecotyAccessDeniedEventArgs : EventArgs
    {
        public string DirPath { private set; get; }
        public DirecotyAccessDeniedEventArgs(string wrongPath)
        {
            this.DirPath = wrongPath;
        }
    }
    public class DirectoryWorker
    {
       
        public delegate void DirectoryAccessHandler(object sender, DirecotyAccessDeniedEventArgs e);
        public event DirectoryAccessHandler DirectoryAccessEvent;
        private MD5 _Md5Haser;
        private object sync = new object();
        public MD5 GetMD5Haser
        {
            get
            {
                if (_Md5Haser != null)
                {

                    return _Md5Haser;
                }
                else
                {
                    lock (sync)
                    {
                        if (_Md5Haser != null)
                        {
                            return _Md5Haser;
                        }
                        else
                        {
                            _Md5Haser = MD5.Create();
                            return _Md5Haser;
                        }
                    }
                }
            }

        }

        private string _path;
        private MainSearch _main;
        public DirectoryWorker(string path, MainSearch ms)
        {
            _path = path;
            _main = ms;
        }
        public void DoTask()
        {
            try
            {
                string[] inDirs = Directory.GetDirectories(_path);
                string[] files = Directory.GetFiles(_path);
                List<Task> tasksToWait = new List<Task>();
                if (inDirs.Length != 0)
                {

                    foreach (var dir in inDirs)
                    {
                        DirectoryWorker dw = new DirectoryWorker(dir, _main);
                        dw.DirectoryAccessEvent += _main.dw_DirectoryAccessEvent;
                        var t = Task.Factory.StartNew(dw.DoTask);
                        tasksToWait.Add(t);
                    }

                }
                foreach (var file in files)
                {
                    _main.AddInfoToList(GetFileData(file));
                }
                Task.WaitAll(tasksToWait.ToArray());
            }
            catch (System.UnauthorizedAccessException ue)
            {
                ThrowWrongPathEvent(_path);
            }
        }

        private void ThrowWrongPathEvent(string _path)
        {
            if (DirectoryAccessEvent != null)
            {
                DirectoryAccessEvent(this, new DirecotyAccessDeniedEventArgs(_path));
            }
        }
        private UserFileInfo GetFileData(string pathToFile)
        {
            UserFileInfo fi = new UserFileInfo();
            fi.AllInfo = new FileInfo(pathToFile);
            //File.SetAttributes(pathToFile, FileAttributes.Normal);
            if (_main.DoHash)
            {
                if (_main.CalcHash)
                {

                    using (var fStr = new FileStream(pathToFile, FileMode.Open, FileAccess.Read))
                    {
                        fi.Md5FileHash = GetMD5Haser.ComputeHash(fStr);
                    }
                }
                else
                {
                    fi.Md5FileHash = null;
                }
            }
            return fi;
        }
    }
}
